package com.axon.mvc.patterns.facade {
  import com.axon.base.helpers.AxFailure;
  import com.axon.base.helpers.AxReflectionUtils;
  import com.axon.base.managers.AxErrorManager;
  import com.axon.dataservices.AxDS;
  import com.axon.mvc.helpers.AxMvcUtils;
  import com.axon.mvc.helpers.AxVerbs;
  import com.axon.mvc.patterns.mediator.AxMediator;
  import com.axon.mvc.patterns.proxy.AxProxy;

  import flash.display.DisplayObject;
  import flash.external.ExternalInterface;

  import mx.core.Application;

  import org.puremvc.as3.interfaces.IFacade;
  import org.puremvc.as3.patterns.facade.Facade;

  public class AxFacade extends Facade implements IFacade {

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    public var modelsArray:Array;

    public var registeredAppActions:Object = new Object();

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    protected override function initializeController():void // Don't need to be overriden nor be called. 
    {
      super.initializeController();
      initialize();
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    protected function initialize():void {
    } //  Must be overriden.

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    public function regModelCommandActions(modelClass:Class, actions:Array):void // Must be invoked.
    {
      var modelName:String = AxReflectionUtils.getClassNameByRef(modelClass);

      for each (var item:String in actions)
        registerCommand(modelName + AxMvcUtils.removeAxVerbPrefix(item),
          AxMvcUtils.getCommandClassRefByModelClassRef(modelClass));
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    public function regAppCommandActions(actions:Array):void // Must be invoked.
    {
      var appCommandClass:Class = AxReflectionUtils.getClassRefByFullPath(AxMvcUtils.FULL_PATH_APP_COMMAND);

      for each (var item:String in actions) {
        registerCommand(item, appCommandClass);
        registeredAppActions[item] = "";
      }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    public function regMediator(mediator:AxMediator):void {
      registerMediator(mediator)
    } // Must be invoked.

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    public function regProxy(proxy:AxProxy):void {
      registerProxy(proxy)
    } // Must be invoked.

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    public function unregMediator(mediator:AxMediator):void {
      removeMediator(mediator.getMediatorName())
    } // Must be invoked.

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    public function unregProxy(proxy:AxProxy):void {
      removeProxy(proxy.getProxyName())
    } // Must be invoked.

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    public function startup(app:DisplayObject):void // Must be overriden for models array initialization.
    {
      AxDS.initialize([], modelsArray);

      //TODO - Esse if não está funcionando (foco já aparecer na tela do login).
      if (ExternalInterface.available)
        ExternalInterface.call("s = function() { document.getElementById('" + Application.application.id + "').focus(); }");

      broadcastMessage(this, AxVerbs.STARTUP);
    }

    public function callController(modelClass:Class, action:String, body:Object = null, extraInfo:Object = null):void {
      if (modelClass) {

        var modelName:String = AxReflectionUtils.getClassNameByRef(modelClass);
        var noteName:String = modelName + AxMvcUtils.removeAxVerbPrefix(action);

        if (AxMvcUtils.getCommandClassRefByModelClassRef(modelClass))
          sendNotification(noteName, {sender: this, body: body, extraInfo: extraInfo});
        else
          AxErrorManager.showFailure(new AxFailure(
            "Message for Software Engineers:\n\nHey guys, class " +
            modelName +
            AxMvcUtils.SUFIX_COMMAND +
            " should be implemented."));
      } else {

        if (AxReflectionUtils.getClassRefByFullPath(AxMvcUtils.FULL_PATH_APP_COMMAND))
          sendNotification(action, {sender: this, body: body, extraInfo: extraInfo});

      }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    public function broadcastMessage(sender:Object,
      message:String,
      body:Object = null,
      extraInfo:Object = null):void {
      sendNotification(message, {sender: sender, body: body, extraInfo: extraInfo});
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    public function getMediator(clazz:Class, name:String = null):AxMediator {
      if (name)
        return retrieveMediator(name) as AxMediator;
      else
        return retrieveMediator(AxReflectionUtils.getClassNameByRef(clazz)) as AxMediator;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////

    public function getProxy(clazz:Class, name:String = null):AxProxy {
      if (name)
        return retrieveProxy(name) as AxProxy;
      else
        return retrieveProxy(AxReflectionUtils.getClassNameByRef(clazz)) as AxProxy;
    }

  }
}